/* The file is saved in UTF-8 codepage.
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */
package cz.pecinovsky.english.lootp._134_;


import cz.pecinovsky.english.lootp.manager.Controller;


import cz.pecinovsky.english.lootp.manager.CanvasManager_Envelope.               CanvasManager;


//import cz.pecinovsky.english.lootp.utility.IO;


import cz.pecinovsky.english.lootp._134_.Ring_134_.Ring;
import cz.pecinovsky.english.lootp._134_.IRace_138_.IRace;
import cz.pecinovsky.english.lootp._134_.IRacer_137_.IRacer;
import cz.pecinovsky.english.lootp._134_.RoadField_134_.RoadField;
import cz.pecinovsky.english.lootp._134_.Arrow_134_.Arrow;
import cz.pecinovsky.english.lootp._134_.Vozidlo_B_137_.Vozidlo_B;


import cz.pecinovsky.english.lootp._134_.Závod_137_        .Závod;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ End of ignored starting test - place for imports +++++
//%I+
//
//import cz.pecinovsky.english.lootp.canvasmanager.IControlled;
//import cz.pecinovsky.english.lootp.canvasmanager.Controller;
//import cz.pecinovsky.english.lootp.canvasmanager.CanvasManager;
//%I-

import cz.pecinovsky.english.lootp.utility.NamedColor;
import cz.pecinovsky.english.lootp.utility.IO;
import cz.pecinovsky.english.lootp.utility.Position;
import cz.pecinovsky.english.lootp.utility.Direction8;
//%X+ xxxxx Start of the ovejumped text with declaration of the envelope xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   Není - toto_je_nově_definovaná_třída
 *              Ttt v projektu Ppp
 * Následující: Prozatím není
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class Závod_137_
{    private Závod_137_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- End of the ovejumped text with declaration of the envelope -----


/*******************************************************************************
 * Instance třídy {@code Závod} představují závody, které je možno absolvovat.
 * Závod je charakterizován okruhem, na kterém se pojede.
 * Postupně se k němu mohou hlásit závodníci.
 * Vždy, když jeden závodník závod dokončí, může se přihlásit další.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
//%I+ <138
//public class Závod
//%I-
//%A+ >138
public class Závod implements IRace
//%A-
     {
//== CONSTANT CLASS ATTRIBUTES =================================================

    /** Canvas, na které se bude instance kreslit. */
    private static final CanvasManager CM = CanvasManager.getInstance();



//== VARIABLE CLASS ATTRIBUTES =================================================
//== STATIC CONSTRUCTOR (CLASS INITIALIZER, STATIC INICITALIZING BLOCK) ========
//== CONSTANT INSTANCE ATTRIBUTES ==============================================

    /** Ring, na němž je závoděno. */
    private final Ring okruh;

    /** Pole, z nějž závod odstartuje. */
    private final RoadField start;



//== VARIABLE INSTANCE ATTRIBUTES ==============================================

    /** Kontrolovaný závodník, který se snaží co nejrychleji objet okruh. */
    private IRacer závodník;

    /** Controller, zprostředkovávající ovládání závodníka z klávesnice. */
    private Controller řadič;

    /** Příští pole, na které má závodník dojet a na němž se bude kontrolovat,
     *  zda je skutečně projel.  */
    private RoadField cíl;

    /** Systémový čas v okamžiku startu závodu. */
    private long čas0;



//== CLASS GETTERS AND SETTERS =================================================
//== OTHER NON-PRIVATE CLASS METHODS ===========================================

//##############################################################################
//== CONSTUCTORS AND FACTORY METHODS ===========================================

    /***************************************************************************
     * Vytvoří instanci schopnou pořádat závody na zadaném okruhu.
     *
     * @param okruh Ring, na němž se budou pořádat závody
     */
    public Závod(Ring okruh)
    {
        this.okruh    = okruh;
        this.start    = okruh.getPočátek();
    }



//== ABSTRACT METHODS ==========================================================
//== INSTANCE GETTERS AND SETTERS ==============================================
//== OTHER NON-PRIVATE INSTANCE METHODS ========================================

    /***************************************************************************
     * Zaregistruje zadaného závodníka, umístí jej na start závodu
     * a přihlásí jej jako posluchače klávesnice.
     *
     * @param závodník Závodník registrující se pro daný závod
     */
//%A+ >138
    @Override
//%A-
    public void registration(IRacer závodník)
    {
        if (this.závodník != null) {
            IO.inform("U tohoto závodu je již registrován \n" + this.závodník +
                  "\n\nMusíte se svojí registrací počkat, až dojede do cíle.");
            return;                         //==========>
        }
        Position pozice = start.getPosition();
        int    module  = start.getModule();
        Direction8  direction   = start.getSměr();

        závodník.setPosition(pozice);
        závodník.setModule(module);
        závodník.setDirection(direction);

        this.řadič    = new Controller(závodník);
        this.cíl      = start.getDalší();
        this.závodník = závodník;
        this.čas0     = System.currentTimeMillis();
    }


    /***************************************************************************
     * Prověří, že závodník dojel do správné průběžné cílové pozice.
     * Pokud dojel, připraví další průběžnou pozici, pokud nedojel, čeká dál.
     *
     * @param závodník Závodník hlásící změnu své pozice
     */
//%A+ >138
    @Override
//%A-
    public void checkpoint(IRacer závodník)
    {
        //Testuji, zda se jedná o tutéž instanci, proto operátor !=
        if (this.závodník != závodník) {
            return;                      //==========>
        }
        Position pz = závodník.getPosition();
        Position pc = cíl     .getPosition();
        if (pz.equals(pc)) {
            if (cíl.equals(start)) {
                konecZávodu(závodník);
                return;                  //==========>
            }
            cíl = cíl.getDalší();
        }
    }


    /***************************************************************************
     * Vrátí řetězec sloužící jako textový "podpis" instance
     * používaný především při ladění.
     */
    @Override
    public String toString()
    {
        return "Závod_(okruh=" + okruh + ", závodník=" + závodník + ")";
    }



//== PRIVATE AND AUXILIARY CLASS METHODS =======================================
//== PRIVATE AND AUXILIARY INSTANCE METHODS ====================================

    /***************************************************************************
     * Ukončí závod pro zadaného závodníka.
     *
     * @param závodník Závodník ukončivší závod
     */
    private void konecZávodu(IRacer závodník)
    {
        //Testuji, zda se jedná o tutéž instanci, proto operátor !=
        if (this.závodník != závodník) {
            return;                      //==========>
        }
        long nyní = System.currentTimeMillis();
        this.řadič.konec();
        this.závodník = null;
        int čas = (int)(nyní - čas0 + 50) / 100;
        System.out.println("\n\nZávodík " + závodník.getName() +
               " absolvoval okruh v čase " + čas/10 + "," + čas%10 + " sekund");
    }



//== EMBEDDED TYPES AND INNER CLASSES ==========================================
//== TESTING CLASSES AND METHODS ===============================================

    /***************************************************************************
     * Test method.
     */
    public static void test()
    {
        Arrow  arrow = new Arrow(0, 0, NamedColor.WHITE);
        Vozidlo_B vb = new Vozidlo_B(arrow);

        //Ring, který se pojede, lze vybrat zakomentováním, resp.
        //odkomentováním řádku s tím správným okruhem
        Závod  závod = new Závod(
//                                  Ring.elko(new Position(0,0), NamedColor.HNĚDÁ));
                                  Ring.čtverec(new Position(50,50)));
        vb.setName("Závodník");
        vb.registerFor(závod);
    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main(String[] args)  {  test();  }
    }

//%%- ---- Start of the ovejumped text with closing of the envelope ----
////////////////////////////////////////////////////////////////////////////////
//== TESTING CLASSES AND METHODS ===============================================

    /***************************************************************************
     * Test method.
     */
    public static void test()
    {
        Závod.test();

//        IO.inform("Až se pokocháš, stiskni OK");
//        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main(String[] args)  {  test();  }
}
